import type { ChatBIDataType } from './'
import { lineOptions, pieOptions, scatterOptions } from './options'
import Decimal from 'decimal.js'

function getDecimalPlaces(num: number) {
    const numStr = num.toString();
    const index = numStr.indexOf('.');
    if (index === -1) return 0;
    return numStr.length - index - 1;
}

export const formatBIData = (info: ChatBIDataType) => {
    const resType = ['table']
    let chartData, tableData
    if (info.chart_type) {
        if (info.chart_type === "line_chart") {
            resType.unshift('chart')
            const resOptions = {
                ...lineOptions,
            }
            resOptions.xAxis.data = info.data[info.x_axis_cloums[0]]
            const seriesArr: any[] = []
            info.y_axis_cloums.forEach((item) => {
                seriesArr.push({
                    name: item,
                    type: 'line',
                    data: info.data[item]
                })
            })
            let minVal = Infinity
            let maxVal = -Infinity
            let maxFloatLen = -Infinity
            seriesArr.forEach((sItem: any) => {
                sItem.data.forEach((dItem: any) => {
                    if (dItem) minVal = Math.min(minVal, parseFloat(dItem))
                    if (dItem) maxVal = Math.max(maxVal, parseFloat(dItem))
                    if (dItem) maxFloatLen = Math.max(maxFloatLen, getDecimalPlaces(parseFloat(dItem)))
                })
            })
            const yAxis: any = {
                type: 'value',
                min: 'dataMin',
                max: 'dataMax',
                axisPointer: {
                    snap: true
                },
                axisLabel: {
                    show: true,
                },
            };
            if (minVal !== Infinity && maxVal !== -Infinity) {
                const ratio = 0.1
                let minMaxOffset = parseFloat(((maxVal - minVal) * ratio).toFixed(maxFloatLen))
                if (minMaxOffset < 1 / Math.pow(10, maxFloatLen)) minMaxOffset = 0
                yAxis.max = (val: any) => {
                    return new Decimal(val.max).add(new Decimal(minMaxOffset)).toNumber()
                }
                yAxis.min = (val: any) => {
                    return new Decimal(val.min).sub(new Decimal(minMaxOffset)).toNumber()
                }
            }
            resOptions.legend.data = info.y_axis_cloums
            resOptions.series = seriesArr
            resOptions.yAxis = yAxis
            chartData = resOptions
        } else if (info.chart_type === "pie_chart") {
            resType.unshift('chart')
            const resOptions = {
                ...pieOptions,
            }
            const seriesArr: any[] = []
            const obj: any = {
                type: 'pie',
                radius: '50%',
                data: [],
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                }
            }
            info.data[info.x_axis_cloums[0]].forEach((item: any, index: number) => {
                obj.data.push({ value: info.data[info.y_axis_cloums[0]][index], name: item })
            })
            seriesArr.push(obj)
            resOptions.series = seriesArr
            chartData = resOptions
        } else if (info.chart_type === "scatter_plot") {
            resType.unshift('chart')
            const resOptions = {
                ...scatterOptions,
            }
            const seriesArr: any[] = []
            info.x_axis_cloums.forEach((item: string, index: number) => {
                const yData = info.data[info.y_axis_cloums[index]]
                const xData = info.data[item]
                if (yData && xData) {
                    const obj: any = {
                        type: 'scatter',
                        symbolSize: 10,
                        data: []
                    }
                    xData.forEach((dItem: any, dIndex: number) => {
                        obj.data.push([dItem, yData[dIndex]])
                    })
                    seriesArr.push(obj)
                }
            })
            let xMinVal = Infinity
            let xMaxVal = -Infinity
            let yMinVal = Infinity
            let yMaxVal = -Infinity
            let xMaxFloatLen = -Infinity
            let yMaxFloatLen = -Infinity
            seriesArr.forEach((sItem: any) => {
                sItem.data.forEach((dItem: any) => {
                    if (dItem) xMinVal = Math.min(xMinVal, parseFloat(dItem[0]))
                    if (dItem) xMaxVal = Math.max(xMaxVal, parseFloat(dItem[0]))
                    if (dItem) yMinVal = Math.min(yMinVal, parseFloat(dItem[1]))
                    if (dItem) yMaxVal = Math.max(yMaxVal, parseFloat(dItem[1]))
                    if (dItem) xMaxFloatLen = Math.max(xMaxFloatLen, getDecimalPlaces(parseFloat(dItem[0])))
                    if (dItem) yMaxFloatLen = Math.max(yMaxFloatLen, getDecimalPlaces(parseFloat(dItem[1])))
                })
            })
            const yAxis: any = {
                type: 'value',
                min: 'dataMin',
                max: 'dataMax',
                axisPointer: {
                    snap: true
                },
                axisLabel: {
                    show: true,
                },
            };
            const xAxis: any = {
                type: 'value',
                min: 'dataMin',
                max: 'dataMax',
                axisPointer: {
                    snap: true
                },
                axisLabel: {
                    show: true,
                },
            }
            if (xMinVal !== Infinity && xMaxVal !== -Infinity) {
                const ratio = 0.1
                let minMaxOffset = parseFloat(((xMaxVal - xMinVal) * ratio).toFixed(xMaxFloatLen))
                if (minMaxOffset < 1 / Math.pow(10, xMaxFloatLen)) minMaxOffset = 0
                xAxis.max = (val: any) => {
                    return new Decimal(val.max).add(new Decimal(minMaxOffset)).toNumber()
                }
                xAxis.min = (val: any) => {
                    return new Decimal(val.min).sub(new Decimal(minMaxOffset)).toNumber()
                }
            }
            if (yMinVal !== Infinity && yMaxVal !== -Infinity) {
                const ratio = 0.1
                let minMaxOffset = parseFloat(((yMaxVal - yMinVal) * ratio).toFixed(yMaxFloatLen))
                if (minMaxOffset < 1 / Math.pow(10, yMaxFloatLen)) minMaxOffset = 0
                yAxis.max = (val: any) => {
                    return new Decimal(val.max).add(new Decimal(minMaxOffset)).toNumber()
                }
                yAxis.min = (val: any) => {
                    return new Decimal(val.min).sub(new Decimal(minMaxOffset)).toNumber()
                }
            }
            resOptions.yAxis = yAxis
            resOptions.xAxis = xAxis
            resOptions.series = seriesArr
            chartData = resOptions
        }
    }
    const dataKeys = Object.keys(info.data)
    const headerData: any[] = []
    const contentData: any[] = []
    dataKeys.forEach((item) => {
        headerData.push({
            dataIndex: item,
            key: item,
            title: item,
        })
    })
    info.data[dataKeys[0]].forEach((item: any, index: number) => {
        const resObj: any = {}
        dataKeys.forEach((key) => {
            resObj[key] = info.data[key][index]
        })
        contentData.push(resObj)
    })
    tableData = {
        header: headerData,
        content: contentData
    }
    return {
        typeList: resType,
        chart: chartData,
        table: tableData
    }
}